package com.harzone.commons.search.result;

import java.sql.Date;
import java.sql.ResultSetMetaData;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Timestamp;
import java.util.List;

import com.harzone.commons.search.domain.Field;
import com.harzone.commons.search.domain.Record;


/**
 * 結果集
 * @author ls
 * 2014年11月25日上午9:03:45
 */
public class SearchResultSetImpl extends SearchResultSetAdapter {

	protected SearchResultSetMetaData metaData = null;
	
	protected SQLWarning warningChain = null;

	protected boolean wasNull = false;

	protected Record row = null;
	
	protected List<Record> result = null;


	//默认索引
	protected int index = -1;
	
	//字段名称是否转化为小写
	private boolean toLowerCase =  true;
	
	//开始索引是0
	private boolean begin_index_is_0 = true;
	
	public SearchResultSetImpl() {
		super();
	}
	
	/**
	 * 
	 * 创建一个新的实例SearchResultSetImpl.
	 * @param result
	 */
	public SearchResultSetImpl(SearchResult searchResult) {
		this(searchResult,false);
	}
	
	
	/**
	 * 
	 * 创建一个新的实例SearchResultSetImpl.
	 * @param result
	 * @param lowerCass
	 */
	public SearchResultSetImpl(final SearchResult searchResult, final boolean lowerCase) {
		super();
		this.result = searchResult.getResults();
		this.toLowerCase = lowerCase;
		if(begin_index_is_0){
			index = -1;
		}else{
			index = 0;
		}
		metaData = new SearchResultSetMetaDataImpl(searchResult);
	}
	
	 
	private int getIndex(final String name){
		List<Field> list = row.getFields();
		int index = -1;
		boolean exist = false;
		for (Field field : list) {
			index ++;
			if(field.getShowName().equals(name) || field.getName().equals(name)){
				exist = true;
			}
		}
		return exist?index:-1;
	}
	
	
	/**
	 * 是否为空值
	 * @author ls
	 * 2014年11月25日上午9:17:04 
	 * @param obj
	 * @return
	 */
	private boolean isEmpty(Object obj){
		return (obj==null || "".equals(obj.toString().trim()))?true:false;
	}

	@Override
	public boolean absolute(int row) throws SQLException {
		boolean flag = false;
		if(result!=null && result.size()>row-1){
			if(begin_index_is_0){
				if(result.size()>row){
					this.row = this.result.get(row);
					flag = true;
				}
			}else{
				if(result.size()>row-1){
					this.row = this.result.get(row-1);
					flag = true;
				}
			}
		}
		return flag;
	}
 
	@Override
	public void afterLast() throws SQLException {
		index = result.size();
	}

	@Override
	public void beforeFirst() throws SQLException {
		index = -1;
	}
	
	@Override
	public void clearWarnings() throws SQLException {
		warningChain = null;
	}

	@Override
	public void close() throws SQLException {
		if (row != null) {
			row.clear();
			row = null;
		}
		if (this.result != null) {
			result.clear();
			result = null;
		}
	} 

	@Override
	public boolean first() throws SQLException {
		boolean flag = false;
		if(result!=null && result.size()>=0){
			if(begin_index_is_0){
				index = 0;
				this.row = this.result.get(index);
			}else{
				index = 1;
				this.row = this.result.get(index-1);
			}
			flag = true;
		}
		return flag;
	}


	@Override
	public boolean getBoolean(String columnLabel) throws SQLException {
		Object obj = getObject(columnLabel);
		if (Boolean.class.isInstance(obj)) {
			return (Boolean) obj;
		} else if (this.isEmpty(obj)) {
			return false;
		} else if (Number.class.isInstance(obj)) {
			return ((Number) obj).intValue() != 0;
		} else if (String.class.isInstance(obj)) {
			return !((String) obj).equals("0");
		}
		throw new SQLException("Cannot convert column " + columnLabel
				+ " to boolean");
	}

	@Override
	public byte getByte(String columnLabel) throws SQLException {
		Object obj = getObject(columnLabel);
		if (Number.class.isInstance(obj)) {
			return ((Number) obj).byteValue();
		} else if (this.isEmpty(obj)) {
			return 0;
		}
		throw new SQLException("Cannot convert column " + columnLabel
				+ " to byte");
	}

	 
	@Override
	public Date getDate(String columnLabel) throws SQLException {
		Object obj = getObject(columnLabel);
		if (this.isEmpty(obj)) {
			return null;
		}
		try {
			return Date.valueOf((String) obj);
		} catch (Exception e) {
			throw new SQLException("Cannot convert column " + columnLabel
					+ " to date: " + e.toString());
		}
	}


	@Override
	public double getDouble(String columnLabel) throws SQLException {
		try {
			Object obj = getObject(columnLabel);
			if (Number.class.isInstance(obj)) {
				return ((Number) obj).doubleValue();
			} else if (this.isEmpty(obj)) {
				return 0;
			} else if (String.class.isInstance(obj)) {
				return Double.valueOf((String) obj);
			}
			throw new Exception("Illegal conversion");
		} catch (Exception e) {
			throw new SQLException("Cannot convert column " + columnLabel
					+ " to double: " + e.toString());
		}
	}
	
	@Override
	public int getFetchSize() throws SQLException {
		return this.result!=null ? result.size() : 0;
	}
 
	
	@Override
	public float getFloat(String columnLabel) throws SQLException {
		try {
			Object obj = getObject(columnLabel);
			if (Number.class.isInstance(obj)) {
				return ((Number) obj).floatValue();
			} else if (this.isEmpty(obj)) {
				return 0;
			} else if (String.class.isInstance(obj)) {
				return Float.valueOf((String) obj);
			}
			throw new Exception("Illegal conversion");
		} catch (Exception e) {
			throw new SQLException("Cannot convert column " + columnLabel
					+ " to float: " + e.toString());
		}
	}

	@Override
	public String getString(String columnLabel) throws SQLException {
		  // Column index starts from 1, not 0.
	    Object obj = getObject(columnLabel);
	    if (obj == null) {
	      return null;
	    }
	    return String.valueOf(obj);
	}
	
	@Override
	public int getInt(String columnLabel) throws SQLException {
		try {
			Object obj = getObject(columnLabel);
			if (Number.class.isInstance(obj)) {
				return ((Number) obj).intValue();
			} else if (this.isEmpty(obj)) {
				return 0;
			} else if (String.class.isInstance(obj)) {
				return Integer.valueOf((String) obj);
			}
			throw new Exception("Illegal conversion");
		} catch (Exception e) {
			throw new SQLException("Cannot convert column " + columnLabel
					+ " to integer" + e.toString());
		}
	}
 
	@Override
	public long getLong(String columnLabel) throws SQLException {
		try {
			Object obj = getObject(columnLabel);
			if (Number.class.isInstance(obj)) {
				return ((Number) obj).longValue();
			} else if (this.isEmpty(obj)) {
				return 0;
			} else if (String.class.isInstance(obj)) {
				return Long.valueOf((String) obj);
			}
			throw new Exception("Illegal conversion");
		} catch (Exception e) {
			throw new SQLException("Cannot convert column " + columnLabel
					+ " to long: " + e.toString());
		}
	}

	@Override
	public Object getObject(int columnIndex) throws SQLException {
		List<Field> list = row.getFields();
		if(list.size() > columnIndex && columnIndex >= 0){
			return list.get(columnIndex).getValue();
		}
		return null;
	}
	
	@Override
	public Object getObject(String columnLabel) throws SQLException {
		return this.getObject(this.getIndex(columnLabel));
	}


	@Override
	public int getRow() throws SQLException {
		if(begin_index_is_0){
			return index + 1;
		}else{
			return index;
		}
	}

	@Override
	public short getShort(String columnLabel) throws SQLException {
		try {
			Object obj = getObject(columnLabel);
			if (Number.class.isInstance(obj)) {
				return ((Number) obj).shortValue();
			} else if (this.isEmpty(obj)) {
				return 0;
			} else if (String.class.isInstance(obj)) {
				return Short.valueOf((String) obj);
			}
			throw new Exception("Illegal conversion");
		} catch (Exception e) {
			throw new SQLException("Cannot convert column " + columnLabel
					+ " to short: " + e.toString());
		}
	}


	@Override
	public Timestamp getTimestamp(String columnLabel) throws SQLException {
		Object obj = getObject(columnLabel);
		if (this.isEmpty(obj)) {
			return null;
		}
		if (obj instanceof Timestamp) {
			return (Timestamp) obj;
		}
		if (obj instanceof String) {
			return Timestamp.valueOf((String) obj);
		}
		throw new SQLException("Illegal conversion");
	}

 

	@Override
	public SQLWarning getWarnings() throws SQLException {
		return warningChain;
	}

	@Override
	public boolean isClosed() throws SQLException {
		boolean flag = false;
		if(result==null){
			flag = true;
		}
		return flag;
	}

	@Override
	public boolean isFirst() throws SQLException {
		boolean flag = false;
		if(result==null){
			flag = true;
		}else{
			if(begin_index_is_0){
				if(index == 0){
					flag = true;
				}
			}else{
				if(index == 1){
					flag = true;
				}
			}
		}
		return flag;
	}

	@Override
	public boolean isLast() throws SQLException {
		boolean flag = false;
		if(result==null){
			flag = true;
		}else{
			if(begin_index_is_0){
				if(index == result.size()-1){
					flag = true;
				}
			}else{
				if(index == result.size()){
					flag = true;
				}
			}
		}
		return flag;
	}

	@Override
	public boolean last() throws SQLException {
		boolean flag = false;
		if(result!=null && result.size()>=0){
			if(begin_index_is_0){
				index = result.size()-1;
				this.row = this.result.get(index);
			}else{
				index = result.size();
				this.row = this.result.get(index-1);
			}
			flag = true;
		}
		return flag;
	}

	@Override
	public boolean next() throws SQLException {
		boolean flag = false;
		if(result!=null && result.size()>=0){
			if(!this.isLast()){
				index ++;
				if(begin_index_is_0){
					this.row = this.result.get(index);
					flag = true;
				}else{
					if(index-1>=0){
						this.row = this.result.get(index-1);
						flag = true;
					}
				}
			}
		}
		return flag;
	}

	@Override
	public boolean previous() throws SQLException {
		boolean flag = false;
		if(result!=null && result.size()>=0){
			if(!this.isFirst() && index>0){
				index --;
				if(begin_index_is_0){
					this.row = this.result.get(index);
					flag = true;
				}else{
					if(index-1>=0){
						this.row = this.result.get(index-1);
						flag = true;
					}
				}
				
			}
		}
		return flag;
	}

	@Override
	public boolean wasNull() throws SQLException {
		return wasNull;
	}

	public void setRow(Record row) {
		this.row = row;
	}

	@Override
	public boolean getBoolean(int columnIndex) throws SQLException {
		Object obj = getObject(columnIndex);
		if (Boolean.class.isInstance(obj)) {
			return (Boolean) obj;
		} else if (this.isEmpty(obj)) {
			return false;
		} else if (Number.class.isInstance(obj)) {
			return ((Number) obj).intValue() != 0;
		} else if (String.class.isInstance(obj)) {
			return !((String) obj).equals("0");
		}
		throw new SQLException("Cannot convert column " + columnIndex
				+ " to boolean");
	}

	@Override
	public byte getByte(int columnIndex) throws SQLException {
		Object obj = getObject(columnIndex);
		if (Number.class.isInstance(obj)) {
			return ((Number) obj).byteValue();
		} else if (this.isEmpty(obj)) {
			return 0;
		}
		throw new SQLException("Cannot convert column " + columnIndex
				+ " to byte");
	}

	 
	@Override
	public Date getDate(int columnIndex) throws SQLException {
		Object obj = getObject(columnIndex);
		if (this.isEmpty(obj)) {
			return null;
		}

		try {
			return Date.valueOf((String) obj);
		} catch (Exception e) {
			throw new SQLException("Cannot convert column " + columnIndex
					+ " to date: " + e.toString());
		}
	}


	@Override
	public double getDouble(int columnIndex) throws SQLException {
		try {
			Object obj = getObject(columnIndex);
			if (Number.class.isInstance(obj)) {
				return ((Number) obj).doubleValue();
			} else if (this.isEmpty(obj)) {
				return 0;
			} else if (String.class.isInstance(obj)) {
				return Double.valueOf((String) obj);
			}
			throw new Exception("Illegal conversion");
		} catch (Exception e) {
			throw new SQLException("Cannot convert column " + columnIndex
					+ " to double: " + e.toString());
		}
	}
	
	
	@Override
	public float getFloat(int columnIndex) throws SQLException {
		try {
			Object obj = getObject(columnIndex);
			if (Number.class.isInstance(obj)) {
				return ((Number) obj).floatValue();
			} else if (this.isEmpty(obj)) {
				return 0;
			} else if (String.class.isInstance(obj)) {
				return Float.valueOf((String) obj);
			}
			throw new Exception("Illegal conversion");
		} catch (Exception e) {
			throw new SQLException("Cannot convert column " + columnIndex
					+ " to float: " + e.toString());
		}
	}

	@Override
	public String getString(int columnIndex) throws SQLException {
		  // Column index starts from 1, not 0.
	    Object obj = getObject(columnIndex);
	    if (obj == null) {
	      return null;
	    }
	    return String.valueOf(obj);
	}
	 
	@Override
	public int getInt(int columnIndex) throws SQLException {
		try {
			Object obj = getObject(columnIndex);
			if (Number.class.isInstance(obj)) {
				return ((Number) obj).intValue();
			} else if (this.isEmpty(obj)) {
				return 0;
			} else if (String.class.isInstance(obj)) {
				return Integer.valueOf((String) obj);
			}
			throw new Exception("Illegal conversion");
		} catch (Exception e) {
			throw new SQLException("Cannot convert column " + columnIndex
					+ " to integer" + e.toString());
		}
	}
 
	@Override
	public long getLong(int columnIndex) throws SQLException {
		try {
			Object obj = getObject(columnIndex);
			if (Number.class.isInstance(obj)) {
				return ((Number) obj).longValue();
			} else if (this.isEmpty(obj)) {
				return 0;
			} else if (String.class.isInstance(obj)) {
				return Long.valueOf((String) obj);
			}
			throw new Exception("Illegal conversion");
		} catch (Exception e) {
			throw new SQLException("Cannot convert column " + columnIndex
					+ " to long: " + e.toString());
		}
	}

	@Override
	public short getShort(int columnIndex) throws SQLException {
		try {
			Object obj = getObject(columnIndex);
			if (Number.class.isInstance(obj)) {
				return ((Number) obj).shortValue();
			} else if (this.isEmpty(obj)) {
				return 0;
			} else if (String.class.isInstance(obj)) {
				return Short.valueOf((String) obj);
			}
			throw new Exception("Illegal conversion");
		} catch (Exception e) {
			throw new SQLException("Cannot convert column " + columnIndex
					+ " to short: " + e.toString());
		}
	}


	@Override
	public Timestamp getTimestamp(int columnIndex) throws SQLException {
		Object obj = getObject(columnIndex);
		if (this.isEmpty(obj)) {
			return null;
		}
		if (obj instanceof Timestamp) {
			return (Timestamp) obj;
		}
		if (obj instanceof String) {
			return Timestamp.valueOf((String) obj);
		}
		throw new SQLException("Illegal conversion");
	}

	
	@Override
	public ResultSetMetaData getMetaData() throws SQLException {
		return this.metaData;
	}
	 
}
